<template>
  <div class="app-container">
    <el-row :gutter="20">
      <!--侧边部门数据-->
      <el-col :xs="9" :sm="6" :md="5" :lg="4" :xl="4">
        <div class="head-container">
          <el-input
            v-model="deptName"
            clearable
            size="small"
            placeholder="输入部门名称搜索"
            prefix-icon="el-icon-search"
            class="filter-item"
            @input="getDeptDatas"
          />
        </div>
        <el-tree
          :data="deptDatas"
          :load="getDeptDatas"
          :props="defaultProps"
          :expand-on-click-node="false"
          lazy
          @node-click="handleNodeClick"
        />
      </el-col>
      <!--用户数据-->
      <el-col :xs="15" :sm="18" :md="19" :lg="20" :xl="20">
        <!--工具栏-->
        <div class="head-container">
          <div v-if="crud.props.searchToggle">
            <!-- 搜索 -->
            <el-input
              v-model="query.blurry"
              clearable
              size="small"
              placeholder="输入名称或者邮箱搜索"
              style="width: 200px;"
              class="filter-item"
              @keyup.enter.native="crud.toQuery"
            />
            <date-range-picker v-model="query.createTime" class="date-item" />
            <el-select
              v-model="query.enabled"
              clearable
              size="small"
              placeholder="状态"
              class="filter-item"
              style="width: 90px"
              @change="crud.toQuery"
            >
              <el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
            </el-select>
            <rrOperation />
          </div>
          <crudOperation show :permission="permission" />
        </div>
        <!--表单渲染-->
        <el-dialog
          append-to-body
          :close-on-click-modal="false"
          :before-close="crud.cancelCU"
          :visible.sync="cuForSync"
          :title="crud.status.title"
          width="740px"
        >
          <el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
            <el-tabs v-model="activeName" type="card">
              <el-tab-pane label="基础信息" name="first">
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="12">
                    <el-form-item label="用户名" prop="username">
                      <el-input v-model="form.username" class="input" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="12">
                    <el-form-item label="昵称" prop="nickName">
                      <el-input v-model="form.nickName" class="input" />
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="12">
                    <el-form-item label="电话" prop="phone">
                      <el-input v-model="form.phone" class="input" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="12">
                    <el-form-item label="邮箱" prop="email">
                      <el-input v-model="form.email" class="input" />
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="12">
                    <el-form-item label="身份证号" prop="idCardNo">
                      <el-input v-model="form.idCardNo" class="input" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="12">
                    <el-form-item label="性别">
                      <el-radio-group v-model="form.gender" class="input">
                        <el-radio v-for="item in dict.gender_type" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
                      </el-radio-group>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="14">
                    <el-form-item label="部门">
                      <treeselect
                        v-model="form.deptId"
                        :options="depts"
                        :load-options="loadDepts"
                        :append-to-body="true"
                        :z-index="9999"
                        class="input"
                        style="width: 310px;"
                        placeholder="选择部门"
                      />
                    </el-form-item>
                  </el-col>
                  <!-- <el-col :span="12">
                    <el-form-item label="岗位" prop="jobs">
                      <el-select v-model="form.jobs" class="input" multiple placeholder="请选择" @remove-tag="deleteTag"
                        @change="changeJob">
                        <el-option v-for="item in jobs" :key="item.name" :label="item.name" :value="item.id" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="0.5" class="el-row"> -->
                  <el-col :span="10">
                    <el-form-item style="margin-bottom: 0;" label="角色" prop="roles">
                      <el-select
                        v-model="form.roles"
                        style="width: 195px;"
                        multiple
                        placeholder="请选择"
                        @remove-tag="deleteTag"
                        @change="changeRole"
                      >
                        <el-option
                          v-for="item in roles"
                          :key="item.name"
                          :disabled="level !== 1 && item.level <= level"
                          :label="item.name"
                          :value="item.id"
                        />
                      </el-select>
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-tab-pane>

              <el-tab-pane label="个人简介" name="second">
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="12">
                    <el-form-item label="入学年月" prop="enterDate">
                      <el-date-picker v-model="form.enterDate" type="date" placeholder="请选择日期" style="width: 250px;" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="12">
                    <el-form-item label="专业">
                      <el-select v-model="form.majorDepartId" placeholder="请选择" class="input">
                        <el-option v-for="item in majors" :key="item.id" :label="item.name" :value="item.id" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row :gutter="0.5" class="el-row">
                  <el-col :span="24">
                    <el-form-item label="支撑材料">
                      <!--   上传文件   -->
                      <el-upload
                        ref="upload"
                        accept="image/jpeg, image/gif, image/png, image/bmp"
                        list-type="picture-card"
                        :on-change="handleChange"
                        :before-upload="beforeUpload"
                        :auto-upload="false"
                        :headers="headers"
                        :on-success="handleSuccess"
                        :on-error="handleError"
                        :on-preview="handlePictureCardPreview"
                        :file-list="fileList"
                        :action="imgFileUploadApi + '?name=' + form.username"
                      >
                        <i class="el-icon-plus" />
                        <div slot="tip" class="el-upload__tip" style="margin: 0; padding: 0; line-height: 20px;">请上传大小不超过100M图片</div>
                      </el-upload>
                      <el-dialog title="支撑材料" :append-to-body="true" :visible.sync="dialogVisible">
                        <img width="100%" :src="dialogImageUrl" alt="">
                      </el-dialog>
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-tab-pane>
            </el-tabs>
            <el-row>
              <el-form-item v-permission="permission.verify" label="认证状态" prop="verifyStatus">
                <el-select v-model="form.verifyStatus">
                  <el-option v-for="item in dict.verify_status" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
              </el-form-item>
              <el-form-item label="状态">
                <el-radio-group v-model="form.enabled" :disabled="form.id === user.id">
                  <el-radio v-for="item in dict.user_status" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
                </el-radio-group>
              </el-form-item>
            </el-row>
          </el-form>
          <div slot="footer" class="dialog-footer">
            <el-button type="text" @click="crud.cancelCU">取消</el-button>
            <el-button :loading="crud.status.cu === 2" type="primary" @click="upload">确认</el-button>
          </div>
        </el-dialog>
        <!--表格渲染-->
        <el-table ref="table" v-loading="crud.loading" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
          <el-table-column :selectable="checkboxT" type="selection" width="55" />
          <el-table-column :show-overflow-tooltip="true" prop="username" label="用户名" width="70" />
          <el-table-column :show-overflow-tooltip="true" width="80" prop="verifyStatus" label="认证状态">
            <template slot-scope="scope">
              <div v-if="scope.row.verifyStatus==='0'">待认证</div>
              <div v-if="scope.row.verifyStatus=='1'" style="color: limegreen">认证通过</div>
              <div v-if="scope.row.verifyStatus=='2'" style="color: #FF4949">认证未通过</div>
            </template>
          </el-table-column>
          <el-table-column :show-overflow-tooltip="true" prop="nickName" label="昵称" width="80" />
          <el-table-column prop="gender" label="性别" width="50">
            <template slot-scope="scope">
              <div>{{ scope.row.gender === '0' ? '男': (scope.row.gender === '1' ? '女': '未知') }}</div>
            </template>
          </el-table-column>
          <el-table-column :show-overflow-tooltip="true" prop="phone" width="100" label="电话" />
          <el-table-column :show-overflow-tooltip="true" width="160" prop="email" label="邮箱" />
          <el-table-column :show-overflow-tooltip="true" prop="dept.name" label="部门" />
          <el-table-column :show-overflow-tooltip="true" prop="createTime" width="100" label="创建日期">
            <template slot-scope="scope">
              <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
            </template>
          </el-table-column>
          <el-table-column label="状态" align="center" prop="enabled" fixed="right" width="50">
            <template slot-scope="scope">
              <el-switch
                v-model="scope.row.enabled"
                :disabled="user.id === scope.row.id"
                active-color="#409EFF"
                inactive-color="#F56C6C"
                @change="changeEnabled(scope.row, scope.row.enabled)"
              />
            </template>
          </el-table-column>
          <el-table-column v-permission="['admin','user:edit','user:del']" label="操作" width="115" align="center" fixed="right">
            <template slot-scope="scope">
              <udOperation :data="scope.row" :permission="permission" :disabled-dle="scope.row.id === user.id" />
            </template>
          </el-table-column>
        </el-table>
        <!--分页组件-->
        <pagination />
      </el-col>
    </el-row>
  </div>
</template>

<script>
import crudUser from '@/api/system/user'
import {
  getToken
} from '@/utils/auth'
import {
  isvalidPhone
} from '@/utils/validate'
import {
  getDepts,
  getDeptSuperior
} from '@/api/system/dept'
import {
  getAll,
  getLevel
} from '@/api/system/role'
import {
  getAllJob
} from '@/api/system/job'
import CRUD, {
  presenter,
  header,
  form,
  crud
} from '@crud/crud'
import rrOperation from '@crud/RR.operation'
import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
import DateRangePicker from '@/components/DateRangePicker'
import Treeselect from '@riophae/vue-treeselect'
import {
  getMajors
} from '@/api/anniversary/department'
import {
  mapGetters
} from 'vuex'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import {
  LOAD_CHILDREN_OPTIONS
} from '@riophae/vue-treeselect'
let userRoles = []
let userJobs = []
const defaultForm = {
  id: null,
  username: null,
  nickName: null,
  gender: '2',
  email: null,
  idCardNo: null,
  enterDate: null,
  certificatePhotoPath: null,
  verifyStatus: '0',
  enabled: 'false',
  roles: [],
  jobs: [],
  deptId: null,
  dept: {
    id: null
  },
  phone: null,
  majorDepartId: null,
  major: {
    id: null
  }
}
export default {
  name: 'User',
  components: {
    Treeselect,
    crudOperation,
    rrOperation,
    udOperation,
    pagination,
    DateRangePicker
  },
  cruds() {
    return CRUD({
      title: '用户',
      url: 'api/users',
      crudMethod: { ...crudUser
      }
    })
  },
  mixins: [presenter(), header(), form(defaultForm), crud()],
  // 数据字典
  dicts: ['user_status', 'gender_type', 'verify_status'],
  data() {
    // 自定义验证
    const validPhone = (rule, value, callback) => {
      if (!value) {
        callback(new Error('请输入电话号码'))
      } else if (!isvalidPhone(value)) {
        callback(new Error('请输入正确的11位手机号码'))
      } else {
        callback()
      }
    }
    return {
      activeName: 'first',
      height: document.documentElement.clientHeight - 180 + 'px;',
      deptName: '',
      headers: {
        Authorization: getToken()
      },
      fileData: '', // 文件上传数据（多文件合一）
      fileList: [], // upload多文件数组
      uploading: false,
      handledCount: 0,
      dialogImageUrl: '',
      dialogVisible: false,
      depts: [],
      deptDatas: [],
      majors: [],
      jobs: [],
      level: 3,
      roles: [],
      defaultProps: {
        children: 'children',
        label: 'name',
        isLeaf: 'leaf'
      },
      permission: {
        add: ['admin', 'user:add'],
        edit: ['admin', 'user:edit'],
        del: ['admin', 'user:del'],
        verify: ['admin', 'user:verify']
      },
      enabledTypeOptions: [{
        key: 'true',
        display_name: '激活'
      },
      {
        key: 'false',
        display_name: '锁定'
      }
      ],
      rules: {
        username: [{
          required: true,
          message: '请输入用户名',
          trigger: 'blur'
        },
        {
          min: 2,
          max: 20,
          message: '长度在 2 到 20 个字符',
          trigger: 'blur'
        }
        ],
        nickName: [{
          required: true,
          message: '请输入用户昵称',
          trigger: 'blur'
        },
        {
          min: 2,
          max: 20,
          message: '长度在 2 到 20 个字符',
          trigger: 'blur'
        }
        ],
        email: [{
          required: true,
          message: '请输入邮箱地址',
          trigger: 'blur'
        },
        {
          type: 'email',
          message: '请输入正确的邮箱地址',
          trigger: 'blur'
        }
        ],
        idCardNo: [{
          message: '请输入身份证号',
          trigger: 'blur'
        },
        {
          min: 18,
          max: 18,
          message: '身份证号18位',
          trigger: 'blur'
        }
        ],
        phone: [{
          required: true,
          trigger: 'blur',
          validator: validPhone
        }],
        roles: [
          {
            required: true,
            message: '请选择角色',
            trigger: 'blur'
          }
        ]
      }
    }
  },
  computed: {
    ...mapGetters(['user', 'baseApi', 'imgFileUploadApi']),
    cuForSync: {
      get() {
        return this.crud.status.cu > 0
      }
    }
  },
  watch: {
    'form.enterDate'(nv, ov) {
      // console.log(nv)
      if (nv instanceof Date) {
        this.initSelect(nv.getFullYear())
      }
    }
  },
  created() {
    this.crud.msg.add = '新增成功，默认密码：123456'
  },
  mounted: function() {
    const that = this
    window.onresize = function temp() {
      that.height = document.documentElement.clientHeight - 180 + 'px;'
    }
  },
  methods: {
    changeRole(value) {
      userRoles = []
      value.forEach(function(data, index) {
        const role = {
          id: data
        }
        userRoles.push(role)
      })
    },
    changeJob(value) {
      userJobs = []
      value.forEach(function(data, index) {
        const job = {
          id: data
        }
        userJobs.push(job)
      })
    },
    [CRUD.HOOK.afterAddError](crud) {
      this.afterErrorMethod(crud)
    },
    [CRUD.HOOK.afterEditError](crud) {
      this.afterErrorMethod(crud)
    },
    afterErrorMethod(crud) {
      // 恢复select
      const initRoles = []
      const initJobs = []
      userRoles.forEach(function(role, index) {
        initRoles.push(role.id)
      })
      userJobs.forEach(function(job, index) {
        initJobs.push(job.id)
      })
      crud.form.roles = initRoles
      crud.form.jobs = initJobs
    },
    deleteTag(value) {
      userRoles.forEach(function(data, index) {
        if (data.id === value) {
          userRoles.splice(index, value)
        }
      })
    },
    // 新增与编辑前做的操作
    [CRUD.HOOK.afterToCU](crud, form) {
      this.activeName = 'first'
      this.getRoles()
      this.majors = []
      if (form.id == null) {
        this.getDepts()
      } else {
        this.getSupDepts(form.deptId)
      }
      this.fileList = []
      if (form.certificatePhotoPath != null) {
        var arrayOfStrings = form.certificatePhotoPath.split(';')
        for (var i = 0; i < arrayOfStrings.length; i++) {
          if (arrayOfStrings[i].trim() === '') continue

          var url = this.baseApi + '/upload/图片/' + arrayOfStrings[i]
          this.fileList.push({
            name: arrayOfStrings[i],
            url: url
          })
        }
      }
      this.getRoleLevel()
      this.getJobs()
      form.verifyStatus = `${form.verifyStatus}`
      form.enabled = form.enabled.toString()
    },
    // 打开编辑弹窗前做的操作
    [CRUD.HOOK.beforeToEdit](crud, form) {
      userRoles = []
      userJobs = []
      const roles = []
      // const jobs = []
      form.roles.forEach(function(role, index) {
        roles.push(role.id)
        // 初始化编辑时候的角色
        const rol = {
          id: role.id
        }
        userRoles.push(rol)
      })
      // form.jobs.forEach(function(job, index) {
      //   jobs.push(job.id)
      //   // 初始化编辑时候的岗位
      //   const data = {
      //     id: job.id
      //   }
      //   userJobs.push(data)
      // })
      form.roles = roles
      // form.jobs = jobs
      form.gender = `${form.gender}`
      if (form.enterDate) {
        var date = new Date(Number(`${form.enterDate}`))
        if (date) { this.initSelect(date.getFullYear()) }
      }
    },
    // 提交前做的操作
    [CRUD.HOOK.afterValidateCU](crud) {
      // if (!crud.form.deptId) {
      //   this.$message({
      //     message: '部门不能为空',
      //     type: 'warning'
      //   })
      //   return false
      // }
      // else if (crud.form.jobs.length === 0) {
      //   this.$message({
      //     message: '岗位不能为空',
      //     type: 'warning'
      //   })
      //   return false
      // }
      if (crud.form.roles.length === 0) {
        this.$message({
          message: '角色不能为空',
          type: 'warning'
        })
        return false
      }
      crud.form.roles = userRoles
      // crud.form.jobs = userJobs
      if (!crud.form.deptId) {
        crud.form.dept = null
      } else {
        crud.form.dept.id = crud.form.deptId
      }
      if (!crud.form.majorDepartId) {
        crud.form.major = null
      } else {
        crud.form.major.id = crud.form.majorDepartId
      }
      return true
    },
    upload() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          // 向后台发送请求
          if (this.fileList.length === 0) {
            this.form.certificatePhotoPath = ''
            this.crud.submitCU()
          } else {
            var fileNames = ''
            for (var i = 0; i < this.fileList.length; i++) {
              fileNames += this.fileList[i].name + ';'
            }
            // 若未修改图片地址，则只提交表单
            if (this.form.certificatePhotoPath === fileNames) {
              this.crud.submitCU()
            } else {
              // 若修改了图片地址，则上传文件并提交表单
              this.form.certificatePhotoPath = ''
              this.uploading = true
              this.handledCount = 0
              this.$refs.upload.submit()
            }
          }
        } else {
          // 就像用户提示发生错误的消息
          return
        }
      })
    },
    beforeUpload(file) {
      const isIMAGE = file.type === 'image/jpeg' || 'image/gif' || 'image/png'
      let isLt2M = true
      isLt2M = file.size / 1024 / 1024 < 100
      if (!isIMAGE) {
        this.loading = false
        this.$message.error('上传文件只能是图片格式!')
      }
      if (!isLt2M) {
        this.loading = false
        this.$message.error('上传文件大小不能超过 100MB!')
      }
      return isIMAGE && isLt2M
    },
    handleSuccess(response, file, fileList) {
      // this.crud.notify('上传成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
      this.form.certificatePhotoPath += response + ';'
      this.handledCount++
      if (this.handledCount === this.fileList.length) {
        console.log(this.form.certificatePhotoPath)
        this.crud.submitCU()
      }
      //
      // console.log(this.baseApi + "/file/图片/" + response)
      // this.$refs.upload.clearFiles()
    },
    // 监听上传失败
    handleError(e, file, fileList) {
      this.handledCount++
      const msg = JSON.parse(e.message)
      this.$notify({
        title: msg.message,
        type: 'error',
        duration: 2500
      })
      this.loading = false
    },
    // 点击文件列表中已上传的文件时的钩子
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    handleChange(file, fileList) {
      if (this.uploading === false) {
        const existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name)
        if (existFile) {
          this.$message.error('当前文件已经存在!')
          fileList.pop()
        }
        this.fileList = fileList
      }

      // console.log(this.fileList)
      // if (fileList.length > 0) {
      //   this.fileList = [fileList[fileList.length - 1]]
      // }
    },
    // 获取左侧部门数据
    getDeptDatas(node, resolve) {
      const sort = 'id,desc'
      const params = {
        sort: sort
      }
      if (typeof node !== 'object') {
        if (node) {
          params['name'] = node
        }
      } else if (node.level !== 0) {
        params['pid'] = node.data.id
      }
      setTimeout(() => {
        getDepts(params).then((res) => {
          if (resolve) {
            resolve(res.content)
          } else {
            this.deptDatas = res.content
          }
        })
      }, 100)
    },
    getDepts() {
      getDepts({
        enabled: true
      }).then((res) => {
        this.depts = res.content.map(function(obj) {
          if (obj.hasChildren) {
            obj.children = null
          }
          return obj
        })
      })
    },
    getSupDepts(deptId) {
      getDeptSuperior(deptId).then((res) => {
        const date = res.content
        this.buildDepts(date)
        this.depts = date
      })
    },
    buildDepts(depts) {
      depts.forEach((data) => {
        if (data.children) {
          this.buildDepts(data.children)
        }
        if (data.hasChildren && !data.children) {
          data.children = null
        }
      })
    },
    // 获取弹窗内部门数据
    loadDepts({
      action,
      parentNode,
      callback
    }) {
      if (action === LOAD_CHILDREN_OPTIONS) {
        getDepts({
          enabled: true,
          pid: parentNode.id
        }).then((res) => {
          parentNode.children = res.content.map(function(obj) {
            if (obj.hasChildren) {
              obj.children = null
            }
            return obj
          })
          setTimeout(() => {
            callback()
          }, 200)
        })
      }
    },

    // 切换部门
    handleNodeClick(data) {
      if (data.pid === 0) {
        this.query.deptId = null
      } else {
        this.query.deptId = data.id
      }
      this.crud.toQuery()
    },
    // 改变状态
    changeEnabled(data, val) {
      this.$confirm(
        '此操作将 "' +
            this.dict.label.user_status[val] +
            '" ' +
            data.username +
            ', 是否继续？',
        '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      )
        .then(() => {
          crudUser
            .edit(data)
            .then((res) => {
              this.crud.notify(
                this.dict.label.user_status[val] + '成功',
                CRUD.NOTIFICATION_TYPE.SUCCESS
              )
            })
            .catch(() => {
              data.enabled = !data.enabled
            })
        })
        .catch(() => {
          data.enabled = !data.enabled
        })
    },
    // 获取弹窗内角色数据
    getRoles() {
      getAll()
        .then((res) => {
          this.roles = res
        })
        .catch(() => {})
    },
    // 获取弹窗内岗位数据
    getJobs() {
      getAllJob()
        .then((res) => {
          this.jobs = res.content
        })
        .catch(() => {})
    },
    // 获取权限级别
    getRoleLevel() {
      getLevel()
        .then((res) => {
          this.level = res.level
        })
        .catch(() => {})
    },
    checkboxT(row, rowIndex) {
      return row.id !== this.user.id
    },
    initSelect(year) {
      getMajors(year).then(res => {
        this.majors = res
      })
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  /deep/ .vue-treeselect__control,
  /deep/ .vue-treeselect__placeholder,
  /deep/ .vue-treeselect__single-value {
    height: 30px;
    line-height: 30px;
  }
</style>

<style>
  .input {
    width: 250px;
  }

  .el-row {
    margin-bottom: 0px;
    display: flex;
    flex-wrap: wrap
  }
</style>
